package com.tron.dobest.resttemplate;

import com.google.common.base.Charsets;
import com.tron.dobest.config.TronWebConfig;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.FileUtils;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.*;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;

/**
 *
 //指定目标服务解析数据的方式
 headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
 //指定浏览器收到请求时，处理数据的方式
 headers.add("Accept", MediaType.APPLICATION_JSON.toString());
 //乱码问题
 restTemplate.setMessageConverters(Arrays.asList(new StringHttpMessageConverter(StandardCharsets.UTF_8)));
 */

@Api(tags = "RestTemplate使用示例")
@RestController
@RequestMapping("/rest")
public class TronRestTestController {

    private RestTemplate restTemplate = new RestTemplate();

    private final String URI = "http://localhost:8080";

    /**
     *
     * get传值使用占位符
     * --------------------------------getForObject---------------------------------
     *
     * @return object
     */
    @ApiOperation(value = "GET传值-单个参数,发送请求到receive01",notes = "restTemplate.getForObject(URI + \"/rest/receive01?a={1}\", String.class, 1)")
    @GetMapping("/send01")
    public Object send01() {
        String result = restTemplate.getForObject(URI + "/rest/receive01?a={1}", String.class, 1);
        return result;
    }

    /**
     * 校验路径中必须有a参数，如果没有会抛异常
     * value = "b" 取路径中b的值 传递给a
     * name = "b"  取路径中b的值 传递给a
     * defaultValue = "100" 当路径中没用带b时，传递默认值给a(需要确保默认值能转换成功)
     * @param abc
     * @return
     */
    @GetMapping("/receive01")
    public Object receive01(@RequestParam(name = "a",defaultValue = "100") Integer abc) {
        return "接收到send01参数："+abc;
    }


    /**
     *
     * get传值使用占位符
     * -------------------------------getForObject----------------------------------
     *
     * @return
     */
    @GetMapping("/send02")
    public Object send02() {
        String result = restTemplate.getForObject(URI + "/rest/receive02/{1}/{2}?id={3}", String.class, 1, 1, 1);
        return result;
    }

    @GetMapping("/receive02/{page}/{size}")
    public Object receive02(@PathVariable Integer page, @PathVariable Integer size, @RequestParam String id) {
        return "page:" + page + " size:" + size + " id:" + id;
    }


    /**
     *
     * get传值使用占位符
     * 时间处理查看{@link TronWebConfig}
     * -----------------------------------getForObject------------------------------
     *
     * @return
     */
    @GetMapping("/send03")
    public Object send03() {
        String result = restTemplate.getForObject(URI + "/rest/receive03?time={1}", String.class, new Date());
        return result;
    }

    @GetMapping("/receive03")
    public Object receive03(@RequestParam LocalDateTime time) {
        System.out.println(time);
        return time;
    }

    /**
     * get请求路径中直接传时间时的处理方式{@link TronWebConfig}
     * @return
     */
    @GetMapping("/send031")
    public Object send031() {
        String result = restTemplate.getForObject(URI + "/rest/receive031?time={1}", String.class, LocalDateTime.now());
        return result;
    }

    @GetMapping("/receive031")
    public Object receive031( Date time) {
        System.out.println(time);
        return time;
    }


    /**
     * get请求路径中使用对象来接收参数时不能使用@RequestParam注解
     * @return
     */
    @GetMapping("/send032")
    public Object send032() {
        String result = restTemplate.getForObject(URI + "/rest/receive032?time={1}&localDateTime={2}", String.class, LocalDateTime.now(),new Date());
        return result;
    }

    @GetMapping("/receive032")
    public Object receive032(RestTestData restTestData) {
        System.out.println(restTestData);
        return restTestData;
    }

    /**
     *
     * get传值使用占位符
     * 需要加头部验证时，用exchange方法添加 Head到httpEntity对象中。
     * -----------------------------exchange 路径+请求方法+请求体(可为空)+返回值类型+参数 ------------------------------------
     *
     * @return
     */
    @GetMapping("/send04")
    public Object send04() {
        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", "tron");
        HttpEntity<Object> httpEntity = new HttpEntity<>(headers);
        ResponseEntity<String> responseEntity = restTemplate.exchange(URI + "/rest/receive04?id={1}", HttpMethod.PUT, httpEntity, String.class, 1);
        String body = responseEntity.getBody();
        return body;
    }

    /**
     * 获取请求头可以使用@RequestHeader
     * @param id
     * @param request
     * @param head
     * @return
     */
    @GetMapping("/receive04")
    public Object receive04(String id, HttpServletRequest request,@RequestHeader("Authorization") String head) {
        final String authorization = request.getHeader("Authorization");
        return String.format("id=%1$s,Authorization=%2$s,head=%3$s", id, authorization,head);
    }


    /**
     * ---------------------------------post如果不需要加头部信息，可以传null--------------------------------
     *
     * @return
     */
    @GetMapping("/send05")
    public Object send05() {
        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", "tron");
        //指定目标服务解析数据的方式
        headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
        //指定浏览器收到请求时，处理数据的方式
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
        /**
         * key +  数组
         * 根据接受参数类型自动转换
         */
        LinkedMultiValueMap<String, Object> valueMap = new LinkedMultiValueMap<>();
        valueMap.put("names", Arrays.asList("tron", "tron01"));
        HttpEntity<Object> httpEntity = new HttpEntity<>(valueMap, headers);
        String result = restTemplate.postForObject(URI + "/rest/receive05?id={1}", httpEntity, String.class, 1);
        return result;
    }

    @PostMapping("/receive05")
    public Object receive05(Integer id, String[] names) {
        return id + "" + Arrays.toString(names);
    }


    /**
     * ---------------------------------post如果不需要加头部信息，可以直接传map--------------------------------
     *
     * @return
     */
    @GetMapping("/send06")
    public Object send06() {
        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", "tron");
        HashMap<String, Object> map = new HashMap<>();
        map.put("name", "中文");
//        map.put("age", 28);
//        map.put("marry", false);
//        map.put("friends", new String[]{"tom"});
//        map.put("data", Arrays.asList(1, 2, 3, 4, 5));
        map.put("time", new Date());
//        map.put("time", "2020-05-03 12:12:00");
        map.put("localDateTime", LocalDateTime.now());
//        map.put("localDateTime", "2020-05-03 12:12:00");
        HttpEntity<Object> httpEntity = new HttpEntity<>(map, headers);
        String result = restTemplate.postForObject(URI + "/rest/receive06", map, String.class);
        return result;
    }

    /**
     * 使用@requestBody
     * 当请求content_type为：application/json类型的请求，数据类型为json时， 
     * json格式如下：{"x":"x","y":"y"}
     *
     * 不使用@requestBody
     * 当请求content_type为：application/x-www-form-urlencoded类型的或multipart/form-data时，
     * 数据格式为x=111&y=222
     *
     * @param restTestData
     * @return
     */
    @PostMapping("/receive06")
    public Object receive06(@RequestBody RestTestData restTestData) {
        return restTestData;
    }


    /**
     * 发送文件给上传接口
     */
    @GetMapping("/send07")
    public Object send07() throws IOException {
        ResponseEntity<Resource> responseEntity = restTemplate.exchange("http://localhost:8080/getFile", HttpMethod.GET, null, Resource.class);
        final InputStream inputStream = responseEntity.getBody().getInputStream();
        final File file = new File("tron.txt");
        FileUtils.copyToFile(inputStream, file);
        final FileSystemResource fileSystemResource = new FileSystemResource(file);
        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
        param.put("file", Arrays.asList(fileSystemResource));
        final HttpEntity<Object> httpEntity = new HttpEntity<>(param);
        final String result = restTemplate.postForObject(URI + "/rest/receive07", httpEntity, String.class);
        file.delete();
        return result;
    }


    @PostMapping("/receive07")
    public Object receive07(@RequestParam("file") MultipartFile file) {
        return file.getOriginalFilename()+"<===>"+file.getSize();
    }


    /**
     * 文件获取,并返回给前端
     */

    @GetMapping("/getRestFile")
    public void getRestFile(HttpServletResponse response) throws IOException {
        HttpEntity<Object> httpEntity = new HttpEntity<>("tron");
        //设置响应头
        response.addHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode("fileName.txt", Charsets.UTF_8.toString()));
        //获取输出流
        ServletOutputStream outputStream = response.getOutputStream();
        //获取文件
        ResponseEntity<Resource> responseEntity = restTemplate.exchange("http://localhost:8080/getFile", HttpMethod.GET, null, Resource.class);
        //获取输入流
        InputStream inputStream = responseEntity.getBody().getInputStream();
        byte[] buff = new byte[1024];
        int read = 0;
        while ((read = inputStream.read(buff)) != -1) {
            //将文件写入响应
            outputStream.write(buff, 0, read);
        }
        outputStream.close();
        inputStream.close();
    }
}
